<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="2.0"
    exclude-result-prefixes="xd xs xsi rifcs #default bg bgr vxu"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    xmlns:rifcs="http://ands.org.au/standards/rif-cs/registryObjects"
    xmlns:bg="http://www.ibm.com/is/bg/importexport"
    xmlns:bgr="http://www.biogrid.org.au/bg2rifcs"
    xmlns:vxu="http://www.versi.edu.au/xmlutils/vxu.xsl"
    xmlns="http://www.openarchives.org/OAI/2.0/"

    xsi:schemaLocation=
        "http://ands.org.au/standards/rif-cs/registryObjects http://services.ands.org.au/documentation/rifcs/1.2.0/schema/registryObjects.xsd
         http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"    
    >
    
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <xd:doc scope="stylesheet">
        <xd:desc>
            <xd:p><xd:b>Created on:</xd:b> Jul 12, 2011</xd:p>
            <xd:p><xd:b>Author:</xd:b>King Lung Chiu</xd:p>
            <xd:p>XSLT for transforming BioGrid's Business Glossary export into RIFCS format.</xd:p>
        </xd:desc>
    </xd:doc>


    <!-- predefined custom attributes -->
    <xsl:param name="CATEGORY_TYPE">Category Type</xsl:param>
    <xsl:param name="CONTACT_NAME">Contact Name</xsl:param>
    <xsl:param name="CONTACT_ADDRESS">Contact Address</xsl:param>
    <xsl:param name="CONTACT_EMAIL">Contact Email</xsl:param>
    <xsl:param name="CONTACT_PHONE_NUMBER">Contact Phone Number</xsl:param>
    <xsl:param name="TERMS_AND_CONDITIONS">Terms and Conditions</xsl:param>
    <xsl:param name="KEY_WORDS">Key Words</xsl:param>
    <xsl:param name="DISEASE_GROUP">Disease Group</xsl:param>
    <xsl:param name="INSTITUTION">Institution</xsl:param>
    <xsl:param name="URL">URL</xsl:param>
    <xsl:param name="SUBJECT_CODES">Subject Codes</xsl:param>
    <xsl:param name="DATA_COLLECTION_START_DATE">Start Date - Data Collection</xsl:param>
    <xsl:param name="DATA_COLLECTION_END_DATE">End Date - Data Collection</xsl:param>
   
   <!-- TODO: add Collection start / end date? -->
   <!--
      <customAttributeDef
      rid="d7e1d378.a5eb05fa.s9t37c3e5.3na1v2j.17igjp.bnakkal6bg622gjbb4k05"
      name="Start Date - Data Collection" description="Start date for data collection if known"/>
      <customAttributeDef
      rid="d7e1d378.a5eb05fa.s9t37c3ep.jvhqb6i.6t1jeg.uf2rrik3m07r2i7evai7j"
      name="End Date - Data Collection" description="End date for data collection if known."/>   
   -->
    
    <!-- controlled vocabulary: CATEGORY_TYPE -->
    <xsl:param name="BIOGRID">biogrid</xsl:param>
    <xsl:param name="DATABASE">database</xsl:param>
    
    
    <xsl:variable name="exportTimestamp" select='xs:dateTime("1970-01-01T00:00:00Z") + /glossary/@exportTime * xs:dayTimeDuration("PT0.001S")'></xsl:variable>
    <xsl:variable name="formatedExportTimestamp" select="format-dateTime($exportTimestamp, '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]Z')"></xsl:variable>
    
    <xsl:variable name="biogridNode" select="/glossary/categories/category[bgr:isBioGrid(.)][1]"/>    
    <xsl:variable name="biogridMainRepositoryRid" select="$biogridNode/@rid"></xsl:variable>

    <xsl:param name="biogridDatabaseIDPrefix">biogrid:database/BG/categories/category/rid:</xsl:param>
    <xsl:param name="biogridStewardIDPrefix">biogrid:steward/BG/categories/category/steward:</xsl:param>
    <xsl:param name="biogridDiseaseGroupIDPrefix">biogrid:diseaseGroupCollection/</xsl:param>
    <xsl:param name="biogridInstitutionIDPrefix">biogrid:institutionCollection/</xsl:param>
    <xsl:param name="tokenDelimiter" select="'\s*,\s*'" as="xs:string"/>
    <xsl:param name="groupName" select="$biogridNode/@name"/>
    <xsl:variable name="LINEBREAK" select="'&#xA;'"/>
       
    <xsl:param name="biogridURL" select="if (bgr:attributeValue($biogridNode, $URL) != '')
                                            then bgr:attributeValue($biogridNode, $URL)
                                            else 'http://www.biogrid.org.au/'"/>
    <xsl:param name="genericCollectionDescFooter" select="concat(
        $LINEBREAK, $LINEBREAK,
        'BioGrid Australia Limited provides a secure research platform ',
        'and infrastructure that enables access to real-time clinical, ', 
        'imaging and biospecimen data across jurisdictions, ',
        'institutions and diseases.')"/>
    
    <xsl:param name="originatingSource" select="$biogridURL"/>
    <xsl:param name="oaiMetadataPrefix" select="'rif'"/>
    <!--<xsl:param name="targetFormat" select="'rifcs'"/>-->
    <xsl:param name="targetFormat" select="'oai-rif'"/>

    <!-- the RIF-CS version our OAI-CAT is currently bound to -->
    <xsl:param name="rifcsSchemaLocation_1.0.1">http://ands.org.au/standards/rif-cs/registryObjects http://services.ands.org.au/home/orca/schemata/registryObjects.xsd</xsl:param>
    <!-- the RIF-CS version we're conforming to -->
    <xsl:param name="rifcsSchemaLocation_1.2">http://ands.org.au/standards/rif-cs/registryObjects http://services.ands.org.au/documentation/rifcs/1.2.0/schema/registryObjects.xsd</xsl:param>
    <!--<xsl:param name="rifcsSchemaLocation">http://ands.org.au/standards/rif-cs/registryObjects http://services.ands.org.au/documentation/rifcs/1.2.0/schema/registryObjects.xsd</xsl:param>-->

    <!-- Generic utility functions -->
    <xsl:include href="vxu.xsl"/>
    
    
    <!-- top-level wrapper for document -->
    <xsl:template match="/">

<!--        <xsl:if test="bg2rifcs:validateInput(.) != 'pass'">
            <xsl:message terminate="yes">
                <xsl:text>Invalid input file! Terminating XSLT processing.</xsl:text>
            </xsl:message>
        </xsl:if>
-->        
        <xsl:choose>            
            <xsl:when test="$targetFormat='rifcs'">
                <rifcs:registryObjects>
                    <xsl:attribute name="xsi:schemaLocation" select="$rifcsSchemaLocation_1.2"/>
                    <xsl:apply-templates select="glossary/categories" />
                </rifcs:registryObjects>
            </xsl:when>
            
            <xsl:otherwise>
                <collection xmlns="http://www.openarchives.org/OAI/2.0/">
                    <xsl:apply-templates select="glossary/categories" />
                </collection>                
            </xsl:otherwise>            
        </xsl:choose>
        
    </xsl:template>
    
    
    <!-- select the relevant categories and stewards -->
    <xsl:template match="/glossary/categories">

        <!-- process every 1st and 2nd level categories
             - 1st level = BioGrid itself
             - 2nd level = databases aggregated within BioGrid -->
        <xsl:apply-templates
            select="category[bgr:isBioGrid(.) or bgr:isDatabase(.)]"
            mode="genericObjectTemplate"/>      
        
        <xsl:variable name="categories" select="."/>
        <!-- create institution and disease group collections -->
        <xsl:for-each select="($INSTITUTION, $DISEASE_GROUP)">
            <xsl:variable name="COLLECTION_TYPE" select="."/>
            
            <xsl:for-each-group select="$categories/category[bgr:isDatabase(.)]"
                group-by="bgr:normalizedAttributeValueTokens(., $COLLECTION_TYPE, $tokenDelimiter)">
                <xsl:variable
                    name="targetCollectionName"
                    select="bgr:map(
                    current-grouping-key(),
                    bgr:normalizedAttributeValueTokens(current-group()[1], $COLLECTION_TYPE, $tokenDelimiter),
                    tokenize(bgr:attributeValue(current-group()[1], $COLLECTION_TYPE), $tokenDelimiter))"/>
                <xsl:apply-templates select="bgr:attribute(current-group()[1], $COLLECTION_TYPE)"
                    mode="genericObjectTemplate">
                    <xsl:with-param name="collectionName" select="$targetCollectionName"/>
                    <xsl:with-param name="collectionType" select="$COLLECTION_TYPE"/>
                    <xsl:with-param name="databases" select="current-group()"/>
                </xsl:apply-templates>
            </xsl:for-each-group>
            
        </xsl:for-each>

        <!-- process every unique steward from the above categories -->
        <!--        <xsl:for-each-group
            select="category[bgr:isBioGrid(.) or bgr:isDatabase(.)]/steward"
            group-by="@userName">
            <xsl:apply-templates select="current-group()[1]" mode="genericObjectTemplate"></xsl:apply-templates>
        </xsl:for-each-group>-->

    </xsl:template>
    
    
    <!-- per-record wrapper: general -->
    <!--<xsl:template match="category | steward" mode="genericObjectTemplate">-->
    <xsl:template match="category | customAttributeValue" mode="genericObjectTemplate"><!-- name="genericObjectTemplate">-->
        <xsl:param name="collectionName" select="''" as="xs:string"/>
        <xsl:param name="collectionType" select="''" as="xs:string"/>
        <xsl:param name="databases"/>
            
        <xsl:choose>
            <xsl:when test="$targetFormat='rifcs'">
                <xsl:apply-templates select="." mode="rifcsObjectTemplate">
                    <xsl:with-param name="collectionName" select="$collectionName"/>
                    <xsl:with-param name="collectionType" select="$collectionType"/>
                    <xsl:with-param name="databases" select="$databases"/>
                </xsl:apply-templates>
            </xsl:when>
            
            <xsl:otherwise>
                <xsl:variable name="rifcsKeyValue">
                    <xsl:call-template name="rifcsKeyValue">
                        <xsl:with-param name="input" select="$collectionName"/>
                        <xsl:with-param name="identifierType" select="$collectionType"/>
                    </xsl:call-template>
                </xsl:variable>
                <record>
                    <database:recordid xmlns:database="http://www.oclc.org/pears/">
                        <xsl:value-of select="concat($rifcsKeyValue, '/', $oaiMetadataPrefix)"/>
                    </database:recordid>
                    <header>
                        <identifier><xsl:value-of select="$rifcsKeyValue"/></identifier>
                        <datestamp><xsl:value-of select="$formatedExportTimestamp"/></datestamp>
                    </header>
                    <metadata>
                        <rifcs:registryObjects>
                            <xsl:attribute name="xsi:schemaLocation" select="$rifcsSchemaLocation_1.0.1"/>
                            <xsl:apply-templates select="." mode="rifcsObjectTemplate">
                                <xsl:with-param name="collectionName" select="$collectionName"/>
                                <xsl:with-param name="collectionType" select="$collectionType"/>
                                <xsl:with-param name="databases" select="$databases"/>
                            </xsl:apply-templates>
                        </rifcs:registryObjects>
                    </metadata>
                 </record>
            </xsl:otherwise>            
        </xsl:choose>
        
    </xsl:template>


    <!-- per-record wrapper: rifcs -->
    <!--<xsl:template match="category | steward" mode="rifcsObjectTemplate">-->
    <xsl:template match="category | customAttributeValue" mode="rifcsObjectTemplate">
        <xsl:param name="collectionName" select="''" as="xs:string"/>
        <xsl:param name="collectionType" select="''" as="xs:string"/>
        <xsl:param name="databases"/>
        
        <rifcs:registryObject group="{$groupName}">
            <!-- Common parts -->
            <!--<xsl:attribute name="group"><xsl:value-of select="$groupName"/></xsl:attribute>-->
            <rifcs:key>
                <xsl:call-template name="rifcsKeyValue">
                    <xsl:with-param name="input" select="$collectionName"/>
                    <xsl:with-param name="identifierType" select="$collectionType"/>
                </xsl:call-template>
            </rifcs:key>
            <rifcs:originatingSource type="authoritative"><xsl:value-of select="$originatingSource"/></rifcs:originatingSource>
            
            <!-- Specific parts -->
            <xsl:choose>
                <xsl:when test="$collectionName = '' and bgr:isBioGrid(.)">
                    <xsl:apply-templates select="." mode="createBioGridGroup"/>                    
                </xsl:when>
                <xsl:when test="$collectionName = '' and bgr:isDatabase(.)">
                    <xsl:apply-templates select="." mode="createDatabaseCollection"/>                                        
                </xsl:when>
                <xsl:when test="$collectionName != '' and
                                (bgr:isInstitution(.) or bgr:isDiseaseGroup(.))">
                    <xsl:apply-templates select="." mode="createCustomCollection">
                        <xsl:with-param name="collectionName" select="$collectionName"/>
                        <xsl:with-param name="collectionType" select="$collectionType"/>
                        <xsl:with-param name="databases" select="$databases"/>
                    </xsl:apply-templates>
                </xsl:when>
<!--                <xsl:when test="$collectionName != '' and bgr:isInstitution(.)">
                    <xsl:apply-templates select="." mode="createInstitutionCollection"/>                                        
                </xsl:when>
                <xsl:when test="$collectionName != '' and bgr:isDiseaseGroup(.)">
                    <xsl:apply-templates select="." mode="createDiseaseGroupCollection"/>                                        
                </xsl:when>-->
            </xsl:choose>
            
        </rifcs:registryObject>
    </xsl:template>


    <xsl:template match="category[bgr:isBioGrid(.)]" mode="createBioGridGroup">
        <rifcs:party type="group">
            
            <rifcs:identifier type="local"><xsl:call-template name="rifcsIdentifier"/></rifcs:identifier>
            <rifcs:name type="primary"><rifcs:namePart><xsl:value-of select="@name"/></rifcs:namePart></rifcs:name>
            <xsl:apply-templates select="." mode="createContactDetails"/>
            
<!--            <!-\- BioGrid and each of its databases has one or more custodians -\->
            <xsl:for-each select="steward">
                <rifcs:relatedObject>
                    <rifcs:key><xsl:call-template name="rifcsKeyValue"/></rifcs:key>                
                    <rifcs:relation type="isManagedBy"/>
                </rifcs:relatedObject>
            </xsl:for-each>-->

<!--            <!-\- databases are part of BioGrid -\->
            <xsl:if test="bgr:isDatabase(.)">
                <rifcs:relatedObject>
                    <rifcs:key><xsl:apply-templates select="$biogridNode" mode="rifcsKeyValue"/></rifcs:key>
                    <rifcs:relation type="isPartOf"/>
                </rifcs:relatedObject>
                </xsl:if>-->
            
            <!-- BioGrid has a number of fields of research -->
            <xsl:apply-templates select="bgr:attribute(., $SUBJECT_CODES)"/>
            
            <xsl:apply-templates select="." mode="createDataCollectionDates"/>

            <xsl:copy-of select="vxu:createRIFCSDescription($RIFCS_DESC_TYPE_BRIEF, @shortDescription)"/>
            <xsl:copy-of select="vxu:createRIFCSDescription($RIFCS_DESC_TYPE_FULL, @longDescription)"/>

        </rifcs:party>
    </xsl:template>
    
    
    <xsl:template match="category[bgr:isDatabase(.)]" mode="createDatabaseCollection">
        <rifcs:collection type="dataset">
                        
            <rifcs:identifier type="local"><xsl:call-template name="rifcsIdentifier"/></rifcs:identifier>
            <rifcs:name type="primary"><rifcs:namePart>
                <xsl:value-of select="concat(@name, ', ', $biogridNode/@name)"/>
            </rifcs:namePart></rifcs:name>
           
            <!-- databases share the same contact details as BioGrid itself -->
            <xsl:apply-templates select="$biogridNode" mode="createContactDetails"/>
            <!--<xsl:apply-templates select="." mode="createContactDetails"/>-->

            <!-- databases should have acquisition start & end dates -->
            <!--<xsl:if test="bgr:hasAttribute(., $DATA_COLLECTION_START_DATE) or bgr:hasAttribute(., $DATA_COLLECTION_END_DATE)">-->
            <xsl:apply-templates select="." mode="createDataCollectionDates"/>
           
<!--            <!-\- BioGrid and each of its databases has one or more custodians -\->
            <xsl:for-each select="steward">
                <rifcs:relatedObject>
                    <rifcs:key><xsl:call-template name="rifcsKeyValue"/></rifcs:key>                
                    <rifcs:relation type="isManagedBy"/>
                </rifcs:relatedObject>
            </xsl:for-each>-->
            
            <!-- databases are managed by BioGrid -->
            <rifcs:relatedObject>
                <rifcs:key><xsl:apply-templates select="$biogridNode" mode="rifcsKeyValue"/></rifcs:key>
                <rifcs:relation type="isManagedBy"/>
            </rifcs:relatedObject>           
            
            <!-- databases are part of at least 1 institution collection -->
            <xsl:for-each select="tokenize(bgr:attributeValue(., $INSTITUTION), $tokenDelimiter)">
                <rifcs:relatedObject>
                    <rifcs:key>
                        <xsl:call-template name="rifcsKeyValue">
                            <xsl:with-param name="input" select="."/>
                            <xsl:with-param name="identifierType" select="$INSTITUTION"/>
                        </xsl:call-template>
                    </rifcs:key>
                    <rifcs:relation type="isPartOf"/>
                </rifcs:relatedObject>
            </xsl:for-each>
            
            <!-- databases relate to at least 1 disease group -->
            <xsl:for-each select="tokenize(bgr:attributeValue(., $DISEASE_GROUP), $tokenDelimiter)">
                <rifcs:relatedObject>
                    <rifcs:key>
                        <xsl:call-template name="rifcsKeyValue">
                            <xsl:with-param name="input" select="."/>
                            <xsl:with-param name="identifierType" select="$DISEASE_GROUP"/>
                        </xsl:call-template>
                    </rifcs:key>
                    <rifcs:relation type="isPartOf"/>
                </rifcs:relatedObject>
            </xsl:for-each>
           
           <!-- all databases from BioGrid are in the same field of research -->
           <xsl:apply-templates select="bgr:attribute($biogridNode, $SUBJECT_CODES)"/>
           
            <xsl:copy-of select="vxu:createRIFCSDescription($RIFCS_DESC_TYPE_BRIEF, @shortDescription)"/>
            <xsl:copy-of select="vxu:createRIFCSDescription($RIFCS_DESC_TYPE_FULL, @longDescription)"/>
            <xsl:copy-of select="vxu:createRIFCSDescription(
                $RIFCS_DESC_TYPE_ACCESS_RIGHTS,
                if (bgr:hasAttribute(., $TERMS_AND_CONDITIONS))
                then bgr:attributeValue(., $TERMS_AND_CONDITIONS)
                else bgr:attributeValue($biogridNode, $TERMS_AND_CONDITIONS))"/>

        </rifcs:collection>
    </xsl:template>
    
    
    <xsl:template match="customAttributeValue[bgr:isInstitution(.) or bgr:isDiseaseGroup(.)]" mode="createCustomCollection">
        <xsl:param name="collectionName" select="''" as="xs:string"/>
        <xsl:param name="collectionType" select="''" as="xs:string"/>
        <xsl:param name="databases"/>
        
        <rifcs:collection type="collection">
            
            <rifcs:identifier type="local">
                <xsl:call-template name="rifcsIdentifier">
                    <xsl:with-param name="input" select="$collectionName"/>
                    <xsl:with-param name="identifierType" select="$collectionType"/>
                </xsl:call-template>
            </rifcs:identifier>
            <rifcs:name type="primary"><rifcs:namePart>
                <xsl:value-of select="concat(
                    if($collectionType = $INSTITUTION)
                        then 'Institution Collection: '
                        else 'Disease Group Collection: ',
                    $collectionName,
                    ', ',
                    $biogridNode/@name)"/>
            </rifcs:namePart></rifcs:name>
           
            <!-- all custom collections share the same contact details as BioGrid itself -->
            <xsl:apply-templates select="$biogridNode" mode="createContactDetails"/>           
            <!--<xsl:apply-templates select="." mode="createContactDetails"/>-->
            
            <!-- collections are managed by BioGrid -->
            <rifcs:relatedObject>
                <rifcs:key><xsl:apply-templates select="$biogridNode" mode="rifcsKeyValue"/></rifcs:key>
                <rifcs:relation type="isManagedBy"/>
            </rifcs:relatedObject>
            
           <!-- all institution and disease group collections from BioGrid
              are in the same field of research -->
           <xsl:apply-templates select="bgr:attribute($biogridNode, $SUBJECT_CODES)"/>
           
           <!-- create custom descriptions -->
            <xsl:apply-templates select="." mode="createCustomDescription">
                <xsl:with-param name="collectionName" select="$collectionName"/>
                <xsl:with-param name="collectionType" select="$collectionType"/>
                <xsl:with-param name="databases" select="$databases"/>
            </xsl:apply-templates>
            
            <xsl:copy-of select="vxu:createRIFCSDescription(
                $RIFCS_DESC_TYPE_ACCESS_RIGHTS,
                bgr:attributeValue($biogridNode, $TERMS_AND_CONDITIONS))"/>

        </rifcs:collection>
    </xsl:template>
   
   
    <xsl:template match="customAttributeValue[bgr:isInstitution(.)]" mode="createCustomDescription">
        <xsl:param name="collectionName" select="''" as="xs:string"/>
        <xsl:param name="collectionType" select="''" as="xs:string"/>
        <xsl:param name="databases"/>
    
        <xsl:variable name="dbString" as="xs:string" select="if (count($databases) > 1) then 'databases' else 'database'"/>
        <xsl:variable name="descriptionText" as="xs:string*">          
            <xsl:value-of select="concat(
                'The BioGrid ', $collectionName, ' collection contains the following ',
                count($databases), ' ', $dbString, ':')"/>
            <xsl:for-each select="$databases">
                <xsl:value-of select="concat(
                    $LINEBREAK,
                    $LINEBREAK, 'Database Name: ', @name,
                    $LINEBREAK, 'Disease Group: ', bgr:attributeValue(., $DISEASE_GROUP),
                    $LINEBREAK, 'Brief Description: ', @shortDescription)"/>                
                </xsl:for-each>
            <xsl:value-of select="$genericCollectionDescFooter"/>           
        </xsl:variable>
        
        <xsl:copy-of select="vxu:createRIFCSDescription(
            $RIFCS_DESC_TYPE_BRIEF, string-join($descriptionText, ''))"/>

    </xsl:template>
   

    <xsl:template match="customAttributeValue[bgr:isDiseaseGroup(.)]" mode="createCustomDescription">
        <xsl:param name="collectionName" select="''" as="xs:string"/>
        <xsl:param name="collectionType" select="''" as="xs:string"/>
        <xsl:param name="databases"/>
        
        <xsl:variable
            name="numInstitutions"
            select="count(distinct-values($databases/customAttributes/customAttributeValue[bgr:isInstitution(.)]/tokenize(@value, $tokenDelimiter)))"/>
        <xsl:variable name="dbString" select="if (count($databases) > 1) then 'databases' else 'database'"/>
        <xsl:variable name="instString" select="if ($numInstitutions > 1) then 'institutions' else 'institution'"/>
        <xsl:variable name="descriptionText" as="xs:string*">
            <xsl:value-of select="concat(
                'The BioGrid ', $collectionName, ' collection contains the following ',
                count($databases), ' ', $dbString,
                ' from ', $numInstitutions, ' ', $instString, ':')"/>
            <xsl:for-each select="$databases">
                <xsl:value-of select="concat(
                    $LINEBREAK,
                    $LINEBREAK, 'Database Name: ', @name,
                    $LINEBREAK, 'Contributors: ', bgr:attributeValue(., $INSTITUTION),
                    $LINEBREAK, 'Brief Description: ', @shortDescription)"/>                
            </xsl:for-each>
            <xsl:value-of select="$genericCollectionDescFooter"/>            
        </xsl:variable>
        
        <xsl:copy-of select="vxu:createRIFCSDescription(
            $RIFCS_DESC_TYPE_BRIEF, string-join($descriptionText, ''))"/>

    </xsl:template>
    

    <xsl:template match="category" mode="createDataCollectionDates">
        <xsl:if test="vxu:isW3CDTF(bgr:attributeValue(., $DATA_COLLECTION_START_DATE))
                       or
                      vxu:isW3CDTF(bgr:attributeValue(., $DATA_COLLECTION_END_DATE))">
            <rifcs:coverage>                 
                <rifcs:temporal>                 
                    <xsl:apply-templates select="bgr:attribute(., $DATA_COLLECTION_START_DATE)"/>
                    <xsl:apply-templates select="bgr:attribute(., $DATA_COLLECTION_END_DATE)"/>
                </rifcs:temporal>              
            </rifcs:coverage>
        </xsl:if>
    </xsl:template>    
    
    
    <xsl:template match="category" mode="createContactDetails">
        <xsl:param name="record" select="."/>
        <xsl:for-each select="($CONTACT_ADDRESS, $CONTACT_EMAIL, $CONTACT_PHONE_NUMBER, $URL)">
            <xsl:apply-templates
                select="if (bgr:hasAttribute($record, .))
                        then bgr:attribute($record, .)
                        else bgr:attribute($biogridNode, .)"/>            
        </xsl:for-each>
    </xsl:template>


<!--    <xsl:template match="steward">        
        <rifcs:party>
            
            <xsl:attribute name="type">
                <xsl:choose>
                    <xsl:when test="@type='USER'">person</xsl:when>
                    <xsl:otherwise>group</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            
            <rifcs:identifier type="local"><xsl:call-template name="rifcsIdentifier"/></rifcs:identifier>
            
            <!-\- add name info -\->            
            <xsl:apply-templates select="../customAttributes/customAttributeValue[bgr:isContactName(.)]"/>
            
        </rifcs:party>
    </xsl:template>-->
    
    
    <xsl:template match="customAttributeValue">
        <xsl:choose>
            <xsl:when test="bgr:isContactName(.)">
                <rifcs:name type="primary">
                    <rifcs:namePart>
                        <xsl:value-of select="@value"/>
                    </rifcs:namePart>
                </rifcs:name>
            </xsl:when>
            <xsl:when test="bgr:isContactAddress(.)">
                <rifcs:location>
                    <rifcs:address>
                        <rifcs:physical type="streetAddress">
                            <rifcs:addressPart type="text">
                                <xsl:value-of select="@value"/>
                            </rifcs:addressPart>
                        </rifcs:physical>
                    </rifcs:address>
                </rifcs:location>
            </xsl:when>
            <xsl:when test="bgr:isContactEmail(.)">
                <rifcs:location>
                    <rifcs:address>
                        <rifcs:electronic type="email">
                            <rifcs:value><xsl:value-of select="@value"/></rifcs:value>
                        </rifcs:electronic>
                    </rifcs:address>
                </rifcs:location>
            </xsl:when>
            <xsl:when test="bgr:isContactPhoneNumber(.)">
                <rifcs:location>
                    <rifcs:address>
                        <rifcs:physical>
                            <rifcs:addressPart type="telephoneNumber">
                                <xsl:value-of select="@value"/>
                            </rifcs:addressPart>
                        </rifcs:physical>
                    </rifcs:address>                    
                </rifcs:location>
            </xsl:when>
            <xsl:when test="bgr:isURL(.)">
                <rifcs:location>
                    <rifcs:address>
                        <rifcs:electronic type="url">
                            <rifcs:value>
                                <xsl:value-of
                                    select="if(normalize-space(@value) != '')
                                            then @value
                                            else $biogridURL"/>
                            </rifcs:value>
                        </rifcs:electronic>
                    </rifcs:address>
                </rifcs:location>
            </xsl:when>
           <!--
              Create RIF-CS <subject> elements from 'Subject Codes'
              custom attribute.
              
              Expected input format example:
              <customAttributeValue
                  customAttribute='{$SUBJECT_CODES}'
                  value='ANZSRC: 13039; ANZSRC: 1301; ANZSRC: 1302'
              >
              
              Expected output format example:
              <rifcs:subject type="ANZSRC">13039</rifcs:subject>
              <rifcs:subject type="ANZSRC">1301</rifcs:subject>
              <rifcs:subject type="ANZSRC">1302</rifcs:subject>
           -->           
            <xsl:when test="bgr:isSubjectCodes(.)">
               <xsl:for-each select="tokenize(normalize-space(@value), '\s*;\s*')">
                  <xsl:variable name="vocabName" select="tokenize(., '\s*:\s*')[1]"/>
                  <xsl:variable name="vocabCodes" select="tokenize(., '\s*:\s*')[2]"/>
                  <xsl:for-each select="tokenize($vocabCodes, '\s*,\s*')">
                     <rifcs:subject type="{$vocabName}">
                        <xsl:value-of select="."/>
                     </rifcs:subject>
                  </xsl:for-each>
               </xsl:for-each>
            </xsl:when>          
            <xsl:when test="bgr:isDataCollectionStartDate(.)">
               <xsl:if test="vxu:isW3CDTF(@value)">
                  <rifcs:date type="dateFrom" dateFormat="UTC">
                     <xsl:value-of select="@value"/>
                  </rifcs:date>
               </xsl:if>
            </xsl:when>
            <xsl:when test="bgr:isDataCollectionEndDate(.)">
               <xsl:if test="vxu:isW3CDTF(@value)">
                  <rifcs:date type="dateTo" dateFormat="UTC">
                     <xsl:value-of select="@value"/>
                  </rifcs:date>
               </xsl:if>
            </xsl:when>
           
            <xsl:otherwise>
               <xsl:message terminate="yes">
                  <xsl:text>Error: encountered unsupported custom attribute '</xsl:text>
                     <xsl:value-of select="@customAttribute"/>
                     <xsl:text>'. Terminating.</xsl:text>
               </xsl:message>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:template>
    

    <!-- ======================================================================
        Function to map a given string to another string, using a user-supplied
        lookup table.
        
        The function first calculates the position the given searchTerm occurs
        in leftList, then returns the corresponding string with the same
        position from rightList.
        
        paramemters
        - searchTerm:
        the string to map        
        
        - leftList:
        list of strings that contains the searchTerm
        
        - rightList:
        list of strings that acts as the lookup table
        ====================================================================== -->
    <xsl:function name="bgr:map" as="xs:string">
        <xsl:param name="searchTerm" as="xs:string"/>
        <xsl:param name="leftList" as="xs:string*"/>
        <xsl:param name="rightList" as="xs:string*"/>
        <xsl:variable
            name="index"
            select="if (count(index-of($leftList, $searchTerm)) > 0)
            then subsequence(index-of($leftList, $searchTerm), 1, 1)
            else 0"/>
        <xsl:value-of select="$rightList[$index]"/>
    </xsl:function>
    
    
    <!--
        Generates a RIFCS key's string for a database, steward,
        disease group collection, institution collection or BioGrid itself.
        
        Designed to be invoked via:
        
        - xsl:apply-template,
        when the input is the XML element context node.
        The type of key value created will be automatically decided on based
        on the element supplied. The 'input' and 'identifierType' parameters
        must not be explicitly set, and will be ignored.
        
        or
        
        - xsl:call-template,
        when the inputs are supplied as strings via the
        'input' and 'identifierType' parameters. The supplied identifierType
        is used to decided what type of key value to create from the
        input string, and can only be $DISEASE_GROUP or $INSTITUTION.
        The context node will be ignored.
    -->
    <xsl:template match="category | steward" name="rifcsKeyValue" mode="rifcsKeyValue">
        <xsl:param name="input" select="''" as="xs:string"/>
        <xsl:param name="identifierType" select="''" as="xs:string"/>
        <xsl:variable name="elementIdentifier">
            <xsl:call-template name="rifcsIdentifier">
                <xsl:with-param name="input" select="$input"/>
                <xsl:with-param name="identifierType" select="$identifierType"/>
            </xsl:call-template>
        </xsl:variable>
        
        <xsl:choose>
            <xsl:when test="$input = '' and bgr:isBioGrid(.)">
                <xsl:value-of select="$elementIdentifier"/>
            </xsl:when>
            
            <xsl:when test="$input = '' and bgr:isDatabase(.)">
                <xsl:value-of select="concat($biogridDatabaseIDPrefix, $elementIdentifier)"/>
            </xsl:when>
            
            <xsl:when test="$input = '' and bgr:isSteward(.)">
                <xsl:value-of select="concat($biogridStewardIDPrefix, $elementIdentifier)"/>
            </xsl:when>
            
            <xsl:when test="($input != '') and ($identifierType = $INSTITUTION)">
                <xsl:value-of select="concat($biogridInstitutionIDPrefix, $elementIdentifier)"/>
            </xsl:when>
            
            <xsl:when test="($input != '') and ($identifierType = $DISEASE_GROUP)">
                <xsl:value-of select="concat($biogridDiseaseGroupIDPrefix, $elementIdentifier)"/>
            </xsl:when>
            
            <xsl:otherwise>ERROR: 'rifcsKeyValue' called on incorrect element type '<xsl:value-of select="name(.)"/>'. Make sure element type is listed in the match clause.</xsl:otherwise>
        </xsl:choose>            
    </xsl:template>

    <!--
        Generates a RIFCS identifier string for a database, steward,
        disease group collection, institution collection or BioGrid itself.
        
        Designed to be invoked via:
        
        - xsl:apply-template,
          when the input is the XML element context node.
          The type of identifier created will be automatically decided on based
          on the element supplied. The 'input' and 'identifierType' parameters
          must not be explicitly set, and will be ignored.
          
          or
        
        - xsl:call-template,
          when the inputs are supplied as strings via the
          'input' and 'identifierType' parameters. The supplied identifierType
          is used to decided what type of identifier to create from the
          input string, and can only be $DISEASE_GROUP or $INSTITUTION.
          The context node will be ignored.
    -->
    <xsl:template match="category | steward" name="rifcsIdentifier" mode="rifcsIdentifier">      
        <xsl:param name="input" select="''" as="xs:string"/>
        <xsl:param name="identifierType" select="''" as="xs:string"/>
        <xsl:choose>
            <xsl:when test="($input = '') and bgr:isBioGrid(.)">
                <xsl:value-of select="$biogridURL"/>
            </xsl:when>
            
            <xsl:when test="($input = '') and
                            (bgr:isDatabase(.) or bgr:isParentCategory(.))">
                <xsl:value-of select="@rid"/>
            </xsl:when>
            
            <xsl:when test="($input = '') and bgr:isSteward(.)">
                <xsl:value-of select="substring-before(substring-after(@userName, 'uid='), ',')"/>
            </xsl:when>
            
            <xsl:when test="($input != '') and
                            ($identifierType = $INSTITUTION or $identifierType = $DISEASE_GROUP)">
                <xsl:value-of select="translate(lower-case(normalize-space($input)), ' ', '_')"></xsl:value-of>
            </xsl:when>
            
            <xsl:otherwise>
                <xsl:message terminate="yes">
                    <xsl:text>ERROR: template 'rifcsIdentifier' invoked on incorrect element type '</xsl:text>
                    <xsl:value-of select="name(.)"/>
                    <xsl:text>'. Make sure element type is listed in the match clause.</xsl:text>
                </xsl:message>
            </xsl:otherwise>
<!--            <xsl:otherwise>ERROR: 'rifcsIdentifier' called on incorrect element type '<xsl:value-of select="$elementName"/>'. Make sure element type is listed in the match clause.</xsl:otherwise>-->
        </xsl:choose>            
    </xsl:template>

    <!-- ======================================================================
        Function to create various identifiers out of a BusinessGlossary
        element. Each type of identifier uses a different part of the element to
        construct its value.
        
        paramemters
        - record:
        the element to create an identifier from        
        
        - idType:
        the type of identifier to create                      
        ====================================================================== -->
    <xsl:function name="bgr:rifcsIdentifier" as="xs:string">
        <xsl:param name="record"/>
        <xsl:param name="recordType" as="xs:string"/>
        <xsl:variable name="elementName" select="name($record)"/>
        
        <xsl:choose>
            <!-- identifier for BioGrid -->
            <xsl:when test="$recordType = 'biogrid' and $elementName = 'category'">
                <xsl:value-of select="$biogridURL"/>
            </xsl:when>
                        
            <!-- Invalid identifier type given -->
            <xsl:otherwise>
                <xsl:message terminate="yes">
                    <xsl:text>Error: rifcsIdentifier(record, recordType) failed, no such recordType: </xsl:text>
                    <xsl:value-of select="$recordType"/>
                </xsl:message>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:function>


    <xsl:function name="bgr:isDiseaseGroup" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $DISEASE_GROUP"/>
    </xsl:function>
    
    <xsl:function name="bgr:isInstitution" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $INSTITUTION"/>
    </xsl:function>
    
    <xsl:function name="bgr:isContactName" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $CONTACT_NAME"/>
    </xsl:function>
    
    <xsl:function name="bgr:isContactAddress" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $CONTACT_ADDRESS"/>
    </xsl:function>
    
    <xsl:function name="bgr:isContactEmail" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $CONTACT_EMAIL"/>
    </xsl:function>
    
    <xsl:function name="bgr:isContactPhoneNumber" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $CONTACT_PHONE_NUMBER"/>
    </xsl:function>
    
    <xsl:function name="bgr:isTermsAndConditions" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $TERMS_AND_CONDITIONS"/>
    </xsl:function>
    
    <xsl:function name="bgr:isURL" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $URL"/>
    </xsl:function>
    
    <xsl:function name="bgr:isSubjectCodes" as="xs:boolean">
        <xsl:param name="customAttributeValue"/>
        <xsl:value-of select="$customAttributeValue/@customAttribute = $SUBJECT_CODES"/>
    </xsl:function>
   
   <xsl:function name="bgr:isDataCollectionStartDate" as="xs:boolean">
      <xsl:param name="customAttributeValue"/>
      <xsl:value-of select="$customAttributeValue/@customAttribute = $DATA_COLLECTION_START_DATE"/>
   </xsl:function>
   
   <xsl:function name="bgr:isDataCollectionEndDate" as="xs:boolean">
      <xsl:param name="customAttributeValue"/>
      <xsl:value-of select="$customAttributeValue/@customAttribute = $DATA_COLLECTION_END_DATE"/>
   </xsl:function>
   
   
    <xsl:function name="bgr:isBioGrid" as="xs:boolean">
        <xsl:param name="category"/>
        <xsl:value-of select="(name($category) = 'category') and bgr:hasAttributeValue($category, $CATEGORY_TYPE, $BIOGRID)"/>
    </xsl:function>    

    <xsl:function name="bgr:isDatabase" as="xs:boolean">
        <xsl:param name="category"/>
        <xsl:value-of select="name($category) = 'category' and bgr:hasAttributeValue($category, $CATEGORY_TYPE, $DATABASE)"/>
    </xsl:function>    
    
    <xsl:function name="bgr:isParentCategory" as="xs:boolean">
        <xsl:param name="input"/>
        <xsl:value-of select="name($input) = 'parentCategory'"/>
    </xsl:function>    
    
    <xsl:function name="bgr:isSteward" as="xs:boolean">
        <xsl:param name="input"/>
        <xsl:value-of select="name($input) = 'steward'"/>
    </xsl:function>    


    <!-- ======================================================================
        Function to test whether a given BusinessGlossary category element
        has a particular custom attribute with a specific value.
        
        Returns true if the supplied category has the specified custom attribute
        with the specified value. Returns false otherwise.
        
        paramemters
        - category:
        the category element to test
        
        - attribute:
        the custom attribute to test                      
        
        - value:
        the expected value in the specified custom attribute                      
        ====================================================================== -->
    <xsl:function name="bgr:hasAttributeValue" as="xs:boolean">
        <xsl:param name="category"/>
        <xsl:param name="attribute"/>
        <xsl:param name="value"/>
        <xsl:value-of select="bgr:attributeValue($category, $attribute) = $value"/>
    </xsl:function>    
    
        
    <!-- ======================================================================
        Function to test whether a given BusinessGlossary category element
        has a particular custom attribute set with a non-empty value.
        
        Returns true if the specified custom attribute is set.
        Returns false otherwise.
        
        paramemters
        - category:
        the category element to test
        
        - attribute:
        the custom attribute to test                      
        ====================================================================== -->
    <xsl:function name="bgr:hasAttribute" as="xs:boolean">
        <xsl:param name="category"/>
        <xsl:param name="attribute"/>
        <xsl:value-of select="normalize-space(bgr:attributeValue($category, $attribute)) != ''"/>
    </xsl:function>    
    

    <!-- ======================================================================
        Function to retrieve the tokenized and normalized value of a custom
        attribute from a BusinessGlossary category element.
        
        The attribute value is retrieved using bgr:normalizedAttributeValue(...),
        then tokenized with the supplied token delimiter.
        
        paramemters
        - category:
        the category element to retrieve an attribute from        
        
        - attributeName:
        the custom attribute to retrieve the attribute value from
        
        - tokenDelimiter:
        the delimiter for tokenizing the attribute value
        ====================================================================== -->
    <xsl:function name="bgr:normalizedAttributeValueTokens" as="xs:string*">
        <xsl:param name="category"/>
        <xsl:param name="attributeName" as="xs:string"/>
        <xsl:param name="tokenDelimiter" as="xs:string"/>
        <xsl:sequence select="tokenize(bgr:normalizedAttributeValue($category, $attributeName), $tokenDelimiter)"/>
    </xsl:function>
    
    
    <!-- ======================================================================
        Function to retrieve the normalized value of a custom attribute from a
        BusinessGlossary category element.
        
        The attribute value is retrieved using bgr:attributeValue(...),
        then normalized with the following in order:
        - normalize-space(...)
        - lower-case(...)
        
        paramemters
        - category:
        the category element to retrieve an attribute from        
        
        - attributeName:
        the custom attribute to retrieve the attribute value from                      
        ====================================================================== -->
    <xsl:function name="bgr:normalizedAttributeValue" as="xs:string">
        <xsl:param name="category"/>
        <xsl:param name="attributeName" as="xs:string"/>
        <xsl:value-of select="lower-case(normalize-space(bgr:attributeValue($category, $attributeName)))"/>
     </xsl:function>


    <!-- ======================================================================
        Function to retrieve the value of a custom attribute from a
        BusinessGlossary category element.
        
        paramemters
        - category:
        the category element to retrieve an attribute from        
        
        - attributeName:
        the custom attribute to retrieve the attribute value from                      
        ====================================================================== -->
    <xsl:function name="bgr:attributeValue" as="xs:string">
        <xsl:param name="category"/>
        <xsl:param name="attributeName" as="xs:string"/>
        <xsl:variable name="elementName" select="name($category)"/>
        
        <xsl:choose>
            <!-- Input expected to be a category -->
            <xsl:when test="$elementName = 'category'">
                <xsl:value-of select="bgr:attribute($category, $attributeName)/@value"/>
                <!--<xsl:value-of select="$category/customAttributes/customAttributeValue[@customAttribute = $attributeName]/@value"/>-->
            </xsl:when>
                        
            <!-- Invalid input type -->
            <xsl:otherwise>
                <xsl:message terminate="yes">
                    <xsl:text>Error: getAttribute(category, attributeName) failed, incorrect input type:&#xA;&#xD;</xsl:text>
                    <xsl:text>   expecting category element, but got: </xsl:text>
                    <xsl:value-of select="$elementName"/>
                </xsl:message>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:function>
    

    <!-- ======================================================================
        Function to retrieve a custom attribute node from a BusinessGlossary
        category element.
        
        paramemters
        - category:
        the category element to retrieve an attribute node from        
        
        - attributeName:
        name of the custom attribute node to retrieve                      
        ====================================================================== -->
    <xsl:function name="bgr:attribute">
        <xsl:param name="category"/>
        <xsl:param name="attributeName" as="xs:string"/>
        <xsl:variable name="elementName" select="name($category)"/>
        
        <xsl:choose>
            <!-- Input expected to be a category -->
            <xsl:when test="$elementName = 'category'">
                <xsl:sequence select="$category/customAttributes/customAttributeValue[@customAttribute = $attributeName]"/>
            </xsl:when>
            
            <!-- Invalid input type -->
            <xsl:otherwise>
                <xsl:message terminate="yes">
                    <xsl:text>Error: attribute(category, attributeName) failed, incorrect input type:&#xA;&#xD;</xsl:text>
                    <xsl:text>   expecting category element, but got: </xsl:text>
                    <xsl:value-of select="$elementName"/>
                </xsl:message>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:function>
    
    
    <xsl:function name="bgr:validateInput" as="xs:string">
        <xsl:param name="doc"/>
        <xsl:variable name="errorMessage">
            <xsl:value-of select="
                if ($doc/glossary/categories[@nothere != 'nosuchvalue'])
                then 'invalid input!'
                else 'pass'"/>
        </xsl:variable>
        <xsl:text>error</xsl:text>
        <!--        <xsl:value-of select="$errorMessage"/>-->
    </xsl:function>
    
    
</xsl:stylesheet>